package com.open.capacity.workflow.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.open.capacity.commons.CodeEnum;
import com.open.capacity.commons.Result;
import com.open.capacity.form.service.FormDbTableService;
import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.finance.util.uuid.UUIDUtils;
import com.open.capacity.user.service.SysUserService;
import com.open.capacity.utils.SysUserUtil;
import com.open.capacity.workflow.enums.WFTransportTypes;
import com.open.capacity.workflow.model.*;
import com.open.capacity.workflow.model.WFEngine.*;
import com.open.capacity.workflow.service.*;
import com.open.capacity.workflow.util.ReflectionUtils;
import com.open.capacity.workflow.vo.WFParameter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class WFEngineServiceImpl implements WFEngineService {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private WFProcessinstanceService processinstanceService;
    @Autowired
    private WFSchemeService schemeService;
    @Autowired
    private WFSchemeExtService schemeExtService;
    @Autowired
    private WFTaskService taskService;
    @Autowired
    private WFTaskHistoryService taskHistoryService;
    @Autowired
    private WFConfluenceService confluenceService;
    @Autowired
    private SysUserService userService;
    @Autowired
    private FormDbTableService formDbTableService;

    //流程模板数据
    private WFScheme scheme;
    //流程模板信息数据
    private WFSchemeinfo schemeinfo;
    //流程创建者
    private SysUser processCreater;

    @Override
    public Result<WFContent> bootstraper(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        boolean res = initScheme(parameter);
        if (res) {
            WFNodeInfo startNode = schemeExtService.getStartNode();
            if (startNode == null) {
                result.setResp_code(2);
                result.setResp_msg("获取不到开始节点信息!");
            } else {
                result.setResp_code(CodeEnum.SUCCESS.getCode());
                result.setResp_msg("流程发起初始化成功!");
                WFContent data = new WFContent();
                data.setCurrentNode(startNode);
                data.setScheme(scheme.getScheme());

                List<String> currentNodeIds;
                if (!parameter.getIsNew()) {
                    List<WFTask> taskList = taskService.findUnFinishTasks(parameter.getProcessId());
                    currentNodeIds = taskList.stream().map(WFTask::getId).collect(Collectors.toList());
                    data.setHistorys(taskHistoryService.findTasksByProcessId(parameter.getProcessId()));
                } else {
                    currentNodeIds = new ArrayList<>();
                    currentNodeIds.add(startNode.getId());
                }
                data.setCurrentNodeIds(currentNodeIds);
                result.setData(data);
            }
        } else {
            result.setResp_code(2);
            result.setResp_msg("获取流程模板失败!");
        }
        return result;
    }

    @Override
    public Result<WFContent> getTaskInfo(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        boolean res = initScheme(parameter);
        if (res) {
            // 获取任务实体信息
            WFTask wfTaskEntity = taskService.findById(parameter.getTaskId());
            if (wfTaskEntity.getIsFinished() != 0) {
                result.setResp_code(2);
                result.setResp_msg("该任务已经处理!");
            } else {
                // 获取任务所在节点信息
                WFNodeInfo currentNode = schemeExtService.getNode(wfTaskEntity.getNodeId());
                if (currentNode == null) {
                    result.setResp_code(2);
                    result.setResp_msg("获取不到节点信息!");
                } else {
                    result.setResp_code(CodeEnum.SUCCESS.getCode());
                    result.setResp_msg("获取流程任务信息成功!");

                    WFContent content = new WFContent();
                    List<WFTask> tasks = taskService.findTasksByProcessId(parameter.getProcessId());
                    content.setCurrentNodeIds(tasks.stream().map(WFTask::getId).collect(Collectors.toList()));
                    content.setCurrentNode(currentNode);

                    // 获取下一个节点所有审核者信息
                    //List<WfTaskEntity> wfTaskList = new List<WfTaskEntity>();
                    //res = GetNextTaskes(currentNode, WfTransportType.Agree, wfTaskList, parameter);

                    content.setScheme(scheme.getScheme());
                    if (!parameter.getIsNew()) {
                        content.setHistorys(taskHistoryService.findTasksByProcessId(parameter.getProcessId()));
                    }
                    result.setData(content);
                }
            }
        } else {
            result.setResp_code(2);
            result.setResp_msg("获取流程模板失败!");
        }
        return result;
    }

    @Override
    public Result<WFContent> getProcessInfo(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        // 初始化模板信息
        boolean res = initScheme(parameter);
        if (res) {
            // 获取任务实体信息
            WFTask wfTaskEntity;
            WFNodeInfo currentNode;
            WFNodeInfo startNode = schemeExtService.getStartNode();
            if (StringUtils.isNotEmpty(parameter.getTaskId())) {
                wfTaskEntity = taskService.findById(parameter.getTaskId());
            } else {

                wfTaskEntity = taskService.findTasksByProcessIdAndNodeId(parameter.getProcessId(), startNode.getId());
            }


            // 获取任务所在节点信息
            if (wfTaskEntity != null) {
                currentNode = schemeExtService.getNode(wfTaskEntity.getNodeId());
            } else {
                currentNode = schemeExtService.getNode(startNode.getId());
            }

            if (currentNode == null) {
                result.setResp_code(2);
                result.setResp_msg("获取不到节点信息!");
            } else {
                result.setResp_code(CodeEnum.SUCCESS.getCode());
                result.setResp_msg("获取流程实例数据成功!");

                WFContent content = new WFContent();
                List<WFTask> tasks = taskService.findUnFinishTasks(parameter.getProcessId());
                content.setCurrentNodeIds(tasks.stream().map(WFTask::getNodeId).collect(Collectors.toList()));
                content.setCurrentNode(currentNode);

                content.setScheme(scheme.getScheme());
                if (!parameter.getIsNew()) {
                    content.setHistorys(taskHistoryService.findTasksByProcessId(parameter.getProcessId()));
                }
                result.setData(content);
            }
        } else {
            result.setResp_code(2);
            result.setResp_msg("获取流程模板失败!");
        }
        return result;
    }

    @Override
    public Result<WFContent> getProcessInfoByMonitor(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        // 初始化模板信息
        boolean res = initScheme(parameter);
        if (res) {
            // 获取任务实体信息
            WFTask wfTaskEntity;
            WFNodeInfo currentNode;
            WFNodeInfo startNode = schemeExtService.getStartNode();

            List<WFTask> tasks = taskService.findUnFinishTasks(parameter.getProcessId());
            List<String> currentNodeIds = tasks.stream().map(WFTask::getId).collect(Collectors.toList());

            if (StringUtils.isNotEmpty(parameter.getTaskId())) {
                wfTaskEntity = taskService.findById(parameter.getTaskId());
            } else {

                wfTaskEntity = taskService.findTasksByProcessIdAndNodeId(parameter.getProcessId(), currentNodeIds.get(0));
            }


            // 获取任务所在节点信息
            if (wfTaskEntity != null) {
                currentNode = schemeExtService.getNode(wfTaskEntity.getNodeId());
            } else {
                currentNode = schemeExtService.getNode(startNode.getId());
            }

            if (currentNode == null) {
                result.setResp_code(2);
                result.setResp_msg("获取不到节点信息!");
            } else {
                result.setResp_code(CodeEnum.SUCCESS.getCode());
                result.setResp_msg("获取流程实例数据成功!");

                WFContent content = new WFContent();
                content.setCurrentNodeIds(currentNodeIds);
                content.setCurrentNode(currentNode);
                content.setScheme(scheme.getScheme());
                content.setHistorys(taskHistoryService.findTasksByProcessId(parameter.getProcessId()));
                result.setData(content);
            }
        } else {
            result.setResp_code(2);
            result.setResp_msg("获取流程模板失败!");
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<WFContent> create(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        //初始化流程模板
        initScheme(parameter);
        //获取开始节点
        WFNodeInfo startNode = schemeExtService.getStartNode();
        //获取下一个节点任务
        List<WFTask> taskList = new ArrayList<>();
        List<WFTask> readTaskList = new ArrayList<>();
        getNextTasks(startNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);

        //保存一个流程实例
        saveProcess(parameter);

        if (!parameter.getIsNew()) {
            // 如果是重新发起的流程需要获取当前任务
            // 更新当前任务节点
            WFTask currentTask = taskService.findUnFinishTasks(parameter.getProcessId(), startNode.getId());
            if (currentTask != null) {
                taskService.updateStatus(parameter.getProcessId(), startNode.getId(), currentTask.getId(), parameter.getUserId(), parameter.getUserName());
                createTaskHistory(parameter, startNode, currentTask, 1, "【重新发起】" + parameter.getDescription());
            } else { //撤销后重新编辑发起
                processinstanceService.updateStatus(parameter.getProcessId(), 1);
            }
        } else {
            createTaskHistory(parameter, startNode, null, 1, "【发起】" + parameter.getDescription());
        }

        //记录查阅节点
        for (WFTask task : readTaskList) {
            if (parameter.getAuditors() != null) {
                Map<String, WFAuditorModel> auditorModelMap = null;
                try {
                    auditorModelMap = objectMapper.readValue(parameter.getAuditors(), new TypeReference<Map<String, WFAuditorModel>>() {
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error(e.getMessage());
                }
                if (auditorModelMap != null && auditorModelMap.containsKey(task.getNodeId())) {
                    List<WFAuditor> auditors = new ArrayList<>();
                    WFAuditor auditor = new WFAuditor();
                    auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                    auditor.setAuditorId(auditorModelMap.get(task.getNodeId()).getUserId());
                    auditor.setAuditorName(auditorModelMap.get(task.getNodeId()).getUserName());
                    auditors.add(auditor);
                    task.setAuditors(auditors);
                }
            }
            taskService.save(task, parameter.getCompanyId(), parameter.getDepartmentId());
        }

        if (taskList.size() == 0) {
            // 没有任务了表示该流程已经结束了
            WFProcessinstance processinstance = new WFProcessinstance();
            processinstance.setIsFinished(1);
            processinstanceService.saveOrUpdate(processinstance, parameter.getProcessId());
        } else {
            // 记录下面节点任务
            for (WFTask task : taskList) {
                if (parameter.getAuditors() != null) {
                    Map<String, WFAuditorModel> auditorModelMap = null;
                    try {
                        auditorModelMap = objectMapper.readValue(parameter.getAuditors(), new TypeReference<Map<String, WFAuditorModel>>() {
                        });
                    } catch (IOException e) {
                        e.printStackTrace();
                        log.error(e.getMessage());
                    }
                    if (auditorModelMap != null && auditorModelMap.containsKey(task.getNodeId())) {
                        List<WFAuditor> auditors = new ArrayList<>();
                        WFAuditor auditor = new WFAuditor();
                        auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                        auditor.setAuditorId(auditorModelMap.get(task.getNodeId()).getUserId());
                        auditor.setAuditorName(auditorModelMap.get(task.getNodeId()).getUserName());
                        auditors.add(auditor);
                        task.setAuditors(auditors);
                    }
                }

                taskService.save(task, parameter.getCompanyId(), parameter.getDepartmentId());
                if (task.getTaskType().equals(2)) {
                    WFProcessinstance processinstance = new WFProcessinstance();
                    processinstance.setIsAgain(1);
                    processinstanceService.saveOrUpdate(processinstance, parameter.getProcessId());
                }
            }
        }

        result.setResp_code(CodeEnum.SUCCESS.getCode());
        result.setResp_msg("创建流程成功");

        // 触发执行sql语句
        if (StringUtils.isNotEmpty(startNode.getDbSuccessSql())) {
            if (StringUtils.isNotEmpty(startNode.getDbSuccessSql())) {
                if (!excuteSql(parameter.getProcessId(), startNode.getDbSuccessId(), startNode.getDbSuccessSql())) {
                    createTaskHistory(parameter, startNode, null, 1, "新发起一个流程实例【执行sql语句异常】");
                }
            }
        }
        // 触发接口方法  TODO 成功回掉方法后面需要完善
        if (StringUtils.isNotEmpty(startNode.getIocName())) {
            ReflectionUtils.quickInvoke(startNode.getIocName(),parameter.getProcessId());
        }


        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<WFContent> audit(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        WFTask currentTask = taskService.findById(parameter.getTaskId());
        if (currentTask == null) {
            result.setResp_msg("找不到当前任务信息");
            result.setResp_code(2);
        } else if (currentTask.getIsFinished() == 1) {
            result.setResp_msg("当前任务已经被处理完");
            result.setResp_code(2);
        } else {
            // 初始化流程模板
            parameter.setProcessId(currentTask.getProcessId());
            parameter.setIsNew(false);
            initScheme(parameter);
            WFNodeInfo currentNode = schemeExtService.getNode(currentTask.getNodeId());
            if (currentNode == null) {
                result.setResp_msg("获取不到当前审核节点信息,请检查流程模板是否被改动");
                result.setResp_code(2);
            } else {
                // 获取下一个节点任务
                List<WFTask> taskList = new ArrayList<>();
                List<WFTask> readTaskList = new ArrayList<>();
                boolean res = true;
                switch (parameter.getVerifyType())//1.审核同意2.审核不同意3.加签4.加签-同意5.加签-不同意6.确认阅读7.保存草稿(暂时不做处理)8.撤销审核
                {
                    case "1":
                        res = getNextTasks(currentNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                        createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription());
                        result.setResp_msg("流程审核成功");
                        break;
                    case "2":
                        res = getNextTasks(currentNode, WFTransportTypes.Disagree, taskList, readTaskList, parameter);
                        createTaskHistory(parameter, currentNode, currentTask, 2, parameter.getDescription());
                        result.setResp_msg("流程审核成功");
                        break;
                    case "3":
                        // 创建一个任务节点
                        WFTask taskEntity = createTaskSign(currentNode, parameter);
                        taskList.add(taskEntity);
                        parameter.setDescription("请【" + parameter.getAuditorName() + "】审核;" + parameter.getDescription());
                        currentTask.setTaskType(4);
                        createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription());
                        result.setResp_msg("流程加签成功");
                        break;
                    case "4":
                        res = getNextTasks(currentNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                        parameter.setDescription("【加签】" + parameter.getDescription());
                        currentTask.setTaskType(1);
                        createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription());
                        result.setResp_msg("流程审核成功");
                        break;
                    case "5":
                        WFTask taskEntity2 = createTask(currentNode, currentNode, parameter);
                        taskList.add(taskEntity2);
                        parameter.setDescription("【加签】" + parameter.getDescription());
                        currentTask.setTaskType(1);
                        createTaskHistory(parameter, currentNode, currentTask, 2, parameter.getDescription());
                        result.setResp_msg("流程审核成功");
                        break;
                    case "6":
                        res = getNextTasks(currentNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                        createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription());
                        result.setResp_msg("流程确认成功");
                        break;
                }


                // 更新当前任务节点
                taskService.updateStatus(currentTask.getProcessId(), currentTask.getNodeId(), currentTask.getId(), parameter.getUserId(), parameter.getUserName());

                if (parameter.getVerifyType().equals("6")) {
                    result.setResp_code(CodeEnum.SUCCESS.getCode());
                    return result;
                }

                // 记录查阅节点
                for (WFTask task : readTaskList) {
                    if (parameter.getAuditors() != null) {
                        Map<String, WFAuditorModel> auditorModelMap = null;
                        try {
                            auditorModelMap = objectMapper.readValue(parameter.getAuditors(), new TypeReference<Map<String, WFAuditorModel>>() {
                            });
                        } catch (IOException e) {
                            e.printStackTrace();
                            log.error(e.getMessage());
                        }
                        if (auditorModelMap != null && auditorModelMap.containsKey(task.getNodeId())) {
                            List<WFAuditor> auditors = new ArrayList<>();
                            WFAuditor auditor = new WFAuditor();
                            auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                            auditor.setAuditorId(auditorModelMap.get(task.getNodeId()).getUserId());
                            auditor.setAuditorName(auditorModelMap.get(task.getNodeId()).getUserName());
                            auditors.add(auditor);
                            task.setAuditors(auditors);
                        }
                    }
                    taskService.save(task, processCreater.getCompanyId(), processCreater.getDepartmentId());
                }


                if (CollectionUtils.isEmpty(taskList)) {
                    // 没有任务了表示该流程已经结束了
                    WFProcessinstance processinstance = new WFProcessinstance();
                    processinstance.setIsFinished(1);
                    processinstanceService.saveOrUpdate(processinstance, parameter.getProcessId());

                    // 删除流程中一些可有可无的没人操作的步骤
                    taskService.deleteFinishedByUndoTaskByProcessId(parameter.getProcessId());
                } else {
                    // 记录下面节点任务
                    for (WFTask task : taskList) {
                        if (!CollectionUtils.isEmpty(task.getAuditors())) {
                            switch (parameter.getVerifyType())//1.审核同意2.审核不同意3.加签4.加签-同意5.加签-不同意6.确认阅读7.保存草稿(暂时不做处理)
                            {
                                case "1":
                                case "4":
                                case "5":
                                    if (parameter.getAuditors() != null) {
                                        Map<String, WFAuditorModel> auditorModelMap = null;
                                        try {
                                            auditorModelMap = objectMapper.readValue(parameter.getAuditors(), new TypeReference<Map<String, WFAuditorModel>>() {
                                            });
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                            log.error(e.getMessage());
                                        }

                                        if (auditorModelMap != null && auditorModelMap.containsKey(task.getNodeId())) {
                                            List<WFAuditor> auditors = new ArrayList<>();
                                            WFAuditor auditor = new WFAuditor();
                                            auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                                            auditor.setAuditorId(auditorModelMap.get(task.getNodeId()).getUserId());
                                            auditor.setAuditorName(auditorModelMap.get(task.getNodeId()).getUserName());
                                            auditors.add(auditor);
                                            task.setAuditors(auditors);
                                        }
                                    }
                                    break;
                                case "2": // 驳回，原来谁审核就谁审核
                                    WFTask _wfTaskEntity = taskService.findTasksByProcessIdAndNodeId(parameter.getProcessId(), task.getNodeId());
                                    if (_wfTaskEntity != null) {
                                        List<WFAuditor> auditors = new ArrayList<>();
                                        WFAuditor auditor = new WFAuditor();
                                        auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                                        auditor.setAuditorId(_wfTaskEntity.getUpdateUserid());
                                        auditor.setAuditorName(_wfTaskEntity.getAuditorName());
                                        auditors.add(auditor);
                                        task.setAuditors(auditors);
                                    }
                                    break;
                            }

                            taskService.save(task, processCreater.getCompanyId(), processCreater.getDepartmentId());
                            if (task.getTaskType().equals(2)) {
                                WFProcessinstance processinstance = new WFProcessinstance();
                                processinstance.setIsAgain(1);
                                processinstanceService.saveOrUpdate(processinstance, parameter.getProcessId());
                            }
                        }
                    }
                }

                int _res = 1;
                switch (parameter.getVerifyType())//1.审核同意2.审核不同意3.加签4.加签-同意5.加签-不同意6.确认阅读7.保存草稿(暂时不做处理)8.撤销审核
                {
                    case "1":
                    case "4":
                    case "6":
                        if (StringUtils.isNotEmpty(currentNode.getDbSuccessSql())) {
                            if (!excuteSql(parameter.getProcessId(), currentNode.getDbSuccessId(), currentNode.getDbSuccessSql())) {
                                createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription() + "【执行sql语句异常】");
                            }
                        }
                        if (StringUtils.isNotEmpty(currentNode.getCfDbSql())) {
                            if (!excuteSql(parameter.getProcessId(), currentNode.getCfDbId(), currentNode.getCfDbSql())) {
                                createTaskHistory(parameter, currentNode, currentTask, 1, parameter.getDescription() + "【执行sql语句异常】");
                            }
                        }
                        // 触发接口方法  TODO 待完善回掉方法
                        if (StringUtils.isNotEmpty(currentNode.getIocName())) {
                            ReflectionUtils.quickInvoke(currentNode.getIocName(),parameter.getProcessId(),parameter.getDescription());
                        }
                        break;
                    case "2":
                    case "5":
                        _res = 2;
                        if (StringUtils.isNotEmpty(currentNode.getDbFailSql())) {
                            if (!excuteSql(parameter.getProcessId(), currentNode.getDbFailId(), currentNode.getDbFailSql())) {
                                createTaskHistory(parameter, currentNode, currentTask, 2, parameter.getDescription() + "【执行sql语句异常】");
                            }
                        }
                        // 触发接口方法  TODO 待完善回掉方法
//                        if (StringUtils.isNotEmpty(currentNode.getIocName())) {
//                            INodeMethod iNodeMethod = UnityIocHelper.WfInstance.GetService < INodeMethod > (currentNode.iocName);
//                            iNodeMethod.Fail(parameter.processId);
//                        }
                        break;
                }
                // 会签
                if (StringUtils.isNotEmpty(currentNode.getCfDbSql())) {
                    if (!excuteSql(parameter.getProcessId(), currentNode.getCfDbId(), currentNode.getCfDbSql())) {
                        createTaskHistory(parameter, currentNode, currentTask, _res, parameter.getDescription() + "【执行sql语句异常】");
                    }
                }
                // 触发接口方法   TODO 待完善回掉方法
                if (StringUtils.isNotEmpty(currentNode.getCfIocName())) {
                    //INodeMethod iNodeMethod = UnityIocHelper.WfInstance.GetService < INodeMethod > (currentNode.cfIocName);
                    if (currentNode.getCfres()) {
                       // iNodeMethod.Sucess(parameter.processId);
                        ReflectionUtils.quickInvoke(currentNode.getIocName(),parameter.getProcessId(),parameter.getDescription());
                    } else {
                        //失败执行
                        //iNodeMethod.Fail(parameter.processId);
                    }
                }
                result.setResp_code(CodeEnum.SUCCESS.getCode());
            }
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<WFContent> revokeAudit(WFParameter parameter) {
        Result<WFContent> result = new Result<>();
        WFTask currentTask = taskService.findById(parameter.getTaskId());
        if (currentTask == null) {
            result.setResp_msg("找不到当前任务信息");
            result.setResp_code(2);
        } else {
            // 初始化流程模板
            parameter.setProcessId(currentTask.getProcessId());
            parameter.setIsNew(false);
            initScheme(parameter);
            WFNodeInfo currentNode = schemeExtService.getNode(currentTask.getNodeId());
            if (currentNode == null) {
                result.setResp_msg("获取不到当前审核节点信息,请检查流程模板是否被改动");
                result.setResp_code(2);
            } else {
                //删除task记录
                List<WFTask> nextTasks = taskService.findTasksByProcessIdAndPreviousId(currentTask.getProcessId(), currentTask.getNodeId());
                if (CollectionUtil.isNotEmpty(nextTasks)) {
                    nextTasks.forEach(t -> {
                        taskService.delete(t.getId());
                    });
                }
                //删除会签记录
                WFConfluence nextConfluence = confluenceService.findTasksByProcessIdAndPreviousId(currentTask.getProcessId(), currentTask.getNodeId());
                if (nextConfluence != null) {
                    confluenceService.delete(nextConfluence.getId());
                }
                //删除task_history记录
                List<WFTaskHistory> historys = taskHistoryService.findTasksByProcessId(currentTask.getProcessId());
                WFTaskHistory needDelete = historys.stream().filter(item -> item.getNodeId().equals(currentTask.getNodeId())).findFirst().get();
                taskHistoryService.delete(needDelete.getId());
                //清空处理人记录
                currentTask.setUpdateUserid(null);
                currentTask.setUpdateUsername(null);
                currentTask.setIsFinished(0);
                taskService.update(currentTask);

                result.setResp_msg("流程撤销成功");
                result.setResp_code(CodeEnum.SUCCESS.getCode());
            }
        }
        return result;
    }

    @Override
    public Result<List<WFAuditorModel>> getAuditer(WFParameter parameter) {
        Result<List<WFAuditorModel>> result = new Result<>();
        String companyId = parameter.getCompanyId();
        String departmentId = parameter.getDepartmentId();

        List<WFTask> taskList = new ArrayList<>();
        List<WFTask> readTaskList = new ArrayList<>();
        // 获取下一节点
        if (parameter.getIsNew())// 开始发起节点的人
        {
            // 初始化流程模板
            initScheme(parameter);
            // 获取开始节点
            WFNodeInfo startNode = schemeExtService.getStartNode();
            getNextTasks(startNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
        } else {
            if (StringUtils.isNotEmpty(parameter.getTaskId()))// 审核节点
            {
                WFTask currentTask = taskService.findById(parameter.getTaskId());
                parameter.setProcessId(currentTask.getProcessId());
                initScheme(parameter);
                companyId = processCreater.getCompanyId();
                departmentId = processCreater.getDepartmentId();
                WFNodeInfo currentNode = schemeExtService.getNode(currentTask.getNodeId());
                getNextTasks(currentNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
            } else {// 重新发起节点
                initScheme(parameter);
                WFNodeInfo startNode = schemeExtService.getStartNode();
                getNextTasks(startNode, WFTransportTypes.Agree, taskList, readTaskList, parameter);
            }
        }
        if (CollectionUtils.isEmpty(taskList) && CollectionUtils.isEmpty(readTaskList)) {
            result.setResp_code(3); // 表示没有一下节点
        } else {
            result.setResp_code(CodeEnum.SUCCESS.getCode()); // 表示有一下节点
            List<WFAuditorModel> list = new ArrayList<>();
            result.setData(list);
            for (WFTask item : readTaskList) {
                if (!CollectionUtils.isEmpty(item.getAuditors())) {
                    WFAuditorModel auditor = new WFAuditorModel();
                    auditor.setAuditors(item.getAuditors());
                    auditor.setNodeName(item.getNodeName());
                    auditor.setCompanyId(companyId);
                    auditor.setDepartmentId(departmentId);
                    auditor.setNodeId(item.getNodeId());
                    list.add(auditor);
                } else {
                    WFAuditorModel auditor = new WFAuditorModel();
                    auditor.setAll(true);
                    auditor.setNodeId(item.getNodeId());
                    auditor.setNodeName(item.getNodeName());
                    list.add(auditor);
                }
            }
            for (WFTask item : taskList) {
                if (!CollectionUtils.isEmpty(item.getAuditors())) {
                    WFAuditorModel auditor = new WFAuditorModel();
                    auditor.setAuditors(item.getAuditors());
                    auditor.setNodeName(item.getNodeName());
                    auditor.setCompanyId(companyId);
                    auditor.setDepartmentId(departmentId);
                    auditor.setNodeId(item.getNodeId());
                    list.add(auditor);
                } else {
                    WFAuditorModel auditor = new WFAuditorModel();
                    auditor.setAll(true);
                    auditor.setNodeId(item.getNodeId());
                    auditor.setNodeName(item.getNodeName());
                    list.add(auditor);
                }
            }
        }

        return result;

    }


    /**
     * 初始化模板
     *
     * @param parameter
     * @return
     */
    private boolean initScheme(WFParameter parameter) {
        try {
            if (parameter.getIsNew()) {
                schemeinfo = schemeService.findSchemeinfoByCode(parameter.getCompanyId(), parameter.getSchemeCode());
                Assert.notNull(schemeinfo, "当前用户所属机构找不到此流程");
                scheme = schemeService.findSchemeById(schemeinfo.getSchemeId());
            } else {
                // 如果是重新发起的流程实例(获取当前实例的流程模板)
                WFProcessinstance processinstance = processinstanceService.findById(parameter.getProcessId());
                processCreater = userService.findById(processinstance.getCreateUserid());
                schemeinfo = schemeService.findSchemeinfoByCode(parameter.getCompanyId(), processinstance.getSchemeCode());
                scheme = schemeService.findSchemeById(processinstance.getSchemeId());
            }
            schemeExtService.schemeInit(scheme);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 保存实例数据
     *
     * @param parameter
     */
    private void saveProcess(WFParameter parameter) {
        WFProcessinstance processinstance = new WFProcessinstance();
        if (parameter.getIsNew()) {
            processinstance.setId(parameter.getProcessId());
            processinstance.setSchemeId(scheme.getId());
            processinstance.setSchemeCode(schemeinfo.getCode());
            processinstance.setSchemeName(schemeinfo.getName());
            processinstance.setProcessName(parameter.getProcessName());
            processinstance.setProcessLevel(parameter.getProcessLevel());
            processinstance.setCompanyId(parameter.getCompanyId());
            processinstance.setDepartmentId(parameter.getDepartmentId());
            processinstance.setCreateUserid(parameter.getUserId());
            processinstance.setCreateUsername(parameter.getUserName());
            processinstance.setDescription(parameter.getDescription());
            processinstance.setCreateTime(new Date());
            processinstance.setIsFinished(0);
            processinstance.setStatus(1);
            processinstanceService.save(processinstance);
        } else {
            processinstance.setIsAgain(0);
            processinstance.setProcessLevel(parameter.getProcessLevel());
            processinstance.setDescription(parameter.getDescription());
            processinstanceService.saveOrUpdate(processinstance, parameter.getProcessId());
        }
    }

    /**
     * 会签节点判断
     *
     * @param nodeInfo    节点信息
     * @param preNodeInfo
     * @param parameter   参数
     * @param isOk        0 不做处理 1 通过 -1 不通过
     * @return
     */
    private int calcConfluenceNode(WFNodeInfo nodeInfo, WFNodeInfo preNodeInfo, WFParameter parameter, boolean isOk) {
        int res = 0;
        Map<String, Object> params = new HashMap<>();
        params.put("processId", parameter.getProcessId());
        params.put("nodeId", nodeInfo.getId());
        List<WFConfluence> list = confluenceService.findConfluences(params);
        long notOkNum = list.stream().filter(r -> r.getIsOk().equals(0)).count();
        long okNum = list.stream().filter(r -> r.getIsOk().equals(1)).count();
        long allNum = schemeExtService.getPreNodeNum(nodeInfo.getId());

        switch (nodeInfo.getConfluenceType()) {////会签策略1-所有步骤通过，2-一个步骤通过即可，3-按百分比计算
            case 1://所有步骤通过
                if (isOk) {
                    if (allNum == okNum + 1) {
                        res = 1;
                        confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                    } else {
                        WFConfluence confluence = new WFConfluence();
                        confluence.setProcessId(parameter.getProcessId());
                        confluence.setNodeId(nodeInfo.getId());
                        confluence.setFromNoteId(preNodeInfo.getId());
                        confluence.setIsOk(1);

                        confluenceService.save(confluence);
                    }
                } else {
                    res = -1;
                    confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                }
                break;
            case 2:
                if (isOk) {
                    res = 1;
                    confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                } else {
                    if (list.size() + 1 == allNum) {
                        res = -1;
                        confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                    } else {
                        WFConfluence confluence = new WFConfluence();
                        confluence.setProcessId(parameter.getProcessId());
                        confluence.setNodeId(nodeInfo.getId());
                        confluence.setFromNoteId(preNodeInfo.getId());
                        confluence.setIsOk(0);

                        confluenceService.save(confluence);
                    }
                }
                break;
            case 3:
                if (isOk) {
                    if ((okNum + 1) * 100 / allNum > Integer.parseInt(nodeInfo.getConfluenceRate())) {
                        res = 1;
                        confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                    } else {
                        WFConfluence confluence = new WFConfluence();
                        confluence.setProcessId(parameter.getProcessId());
                        confluence.setNodeId(nodeInfo.getId());
                        confluence.setFromNoteId(preNodeInfo.getId());
                        confluence.setIsOk(1);
                        confluenceService.save(confluence);
                    }
                } else {
                    if ((allNum - notOkNum - 1) * 100 / allNum < Integer.parseInt(nodeInfo.getConfluenceRate())) {
                        res = -1;
                        confluenceService.delete(parameter.getProcessId(), nodeInfo.getId());
                    } else {
                        WFConfluence confluence = new WFConfluence();
                        confluence.setProcessId(parameter.getProcessId());
                        confluence.setNodeId(nodeInfo.getId());
                        confluence.setFromNoteId(preNodeInfo.getId());
                        confluence.setIsOk(0);
                        confluenceService.save(confluence);
                    }
                }
                break;
        }
        if (res != 0) {
            // 需要清除下此会签其他发布的任务
            clearConfluenceTask(nodeInfo.getId(), preNodeInfo, parameter.getProcessId());
        }
        return res;
    }


    /**
     * 清除会签其他发布的任务
     *
     * @param nodeId      会签节点主键
     * @param preNodeInfo 上一个节点
     * @param processId   流程实例主键
     */
    private void clearConfluenceTask(String nodeId, WFNodeInfo preNodeInfo, String processId) {
        Map<String, String> hasMap = new HashMap<>();// 记录已经处理的节点ID
        List<WFTask> taskList = taskService.findTasksByProcessId(processId);
        LoginAppUser currentUser = SysUserUtil.getLoginAppUser();
        for (WFTask task : taskList) {
            if (task.getIsFinished().equals(0) && !task.getNodeId().equals(preNodeInfo.getId())) {
                if (hasMap.containsKey(task.getNodeId())) {
                    taskService.updateStatus(hasMap.get(task.getNodeId()), 2, currentUser.getId(), currentUser.getUserName());
                } else if (schemeExtService.isToNode(task.getNodeId(), nodeId)) {
                    hasMap.put(task.getNodeId(), task.getId());
                    taskService.updateStatus(task.getId(), 2, currentUser.getId(), currentUser.getUserName());
                }
            }
        }
    }

    /**
     * 条件节点判断
     *
     * @param nodeInfo  节点信息
     * @param parameter 参数
     * @return
     */
    private boolean calcConditionNode(WFNodeInfo nodeInfo, WFParameter parameter) {
        boolean res = false;
        if (nodeInfo.getConditions().size() > 0) {
            Map<String, Object> formData = null;
            try {
                formData = objectMapper.readValue(parameter.getFormData(), Map.class);
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
            for (WFCondition condition : nodeInfo.getConditions()) {
                res = false;
                if (formData.get(condition.getFieldId()) != null) {
                    String v1 = formData.get(condition.getFieldId()).toString();
                    switch (condition.getCompareType())//比较类型1.等于2.不等于3.大于4.大于等于5.小于6.小于等于7.包含8.不包含9.包含于10.不包含于
                    {
                        case 1:
                            if (v1 == condition.getValue()) {
                                res = true;
                            }
                            break;
                        case 2:
                            if (v1 != condition.getValue()) {
                                res = true;
                            }
                            break;
                        case 3:
                            if (new BigDecimal(v1).compareTo(new BigDecimal(condition.getValue())) > 0) {
                                res = true;
                            }
                            break;
                        case 4:
                            if (new BigDecimal(v1).compareTo(new BigDecimal(condition.getValue())) >= 0) {
                                res = true;
                            }
                            break;
                        case 5:
                            if (new BigDecimal(v1).compareTo(new BigDecimal(condition.getValue())) < 0) {
                                res = true;
                            }
                            break;
                        case 6:
                            if (new BigDecimal(v1).compareTo(new BigDecimal(condition.getValue())) <= 0) {
                                res = true;
                            }
                            break;
                        case 7:
                            if (v1.contains(condition.getValue())) {
                                res = true;
                            }
                            break;
                        case 8:
                            if (!v1.contains(condition.getValue())) {
                                res = true;
                            }
                            break;
                        case 9:
                            if (condition.getValue().contains(v1)) {
                                res = true;
                            }
                            break;
                        case 10:
                            if (!condition.getValue().contains(v1)) {
                                res = true;
                            }
                            break;
                    }
                }
            }
        } else if (StringUtils.isNotEmpty(nodeInfo.getConditionSql())) {
            String conditionSql = nodeInfo.getConditionSql().replace("{processId}", "#{processId}");
            Map<String, Object> params = new HashMap<>();
            params.put("processId", parameter.getProcessId());
            List<Map<String, Object>> result = formDbTableService.findData(nodeInfo.getDbConditionId(), conditionSql, params);
            if (result.size() > 0) {
                res = true;
            }
        } else {
            res = true;
        }
        return res;
    }


    /**
     * 创建流程实例节点任务
     *
     * @param nodeInfo    节点信息
     * @param preNodeInfo 上一节点信息
     * @param parameter   参数
     * @return
     */
    private WFTask createTask(WFNodeInfo nodeInfo, WFNodeInfo preNodeInfo, WFParameter parameter) {
        WFTask task = new WFTask();
        task.setPreviousId(parameter.getProcessId());
        task.setNodeId(nodeInfo.getId());
        task.setNodeName(nodeInfo.getName());
        task.setAuditors(nodeInfo.getAuditors());
        switch (nodeInfo.getType()) {//开始startround;结束endround;一般stepnode;会签节点:confluencenode;条件判断节点：conditionnode;查阅节点：auditornode;
            case "startround":
                task.setAuditors(new ArrayList<>());
                WFAuditor wfAuditor = new WFAuditor();
                wfAuditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
                WFProcessinstance processinstance = processinstanceService.findById(parameter.getProcessId());
                wfAuditor.setAuditorId(processinstance.getCreateUserid());
                wfAuditor.setAuditorName(processinstance.getCreateUsername());
                task.getAuditors().add(wfAuditor);
                task.setTaskType(2);
                break;
            case "stepnode":
                task.setTaskType(1);
                break;
            case "auditornode":
                task.setTaskType(3);
                break;
        }
        task.setTimeoutAction(nodeInfo.getTimeoutAction());
        task.setTimeoutNotice(nodeInfo.getTimeoutNotice());
        task.setPreviousId(preNodeInfo.getId());
        task.setPreviousName(preNodeInfo.getName());
        task.setCreateUserid(parameter.getUserId());
        task.setCreateUsername(parameter.getUserName());
        task.setProcessId(parameter.getProcessId());
        return task;
    }


    /**
     * 创建一个加签任务
     *
     * @param preNodeInfo 上一节点信息
     * @param parameter   流程参数信息
     * @return
     */
    private WFTask createTaskSign(WFNodeInfo preNodeInfo, WFParameter parameter) {
        WFTask task = new WFTask();
        task.setProcessId(parameter.getProcessId());
        task.setNodeId(preNodeInfo.getId());
        task.setNodeName(preNodeInfo.getName());
        task.setTaskType(4);
        task.setAuditors(new ArrayList<>());
        WFAuditor auditor = new WFAuditor();
        auditor.setId(UUIDUtils.getOriginalUUIDWithoutBar());
        auditor.setAuditorId(parameter.getAuditorId());
        auditor.setAuditorName(parameter.getAuditorName());
        task.getAuditors().add(auditor);

        task.setPreviousId(preNodeInfo.getId());
        task.setPreviousName(preNodeInfo.getName());
        task.setCreateUserid(parameter.getUserId());
        task.setCreateUsername(parameter.getUserName());

        return task;
    }

    /**
     * 获取接下来需要处理的任务列表
     *
     * @param currentNode   当前节点主键
     * @param transportType 节点流转类型
     * @param taskList      任务列表
     * @param readTaskList  已读任务列表
     * @param parameter     参数
     * @return
     */
    private boolean getNextTasks(WFNodeInfo currentNode, WFTransportTypes transportType, List<WFTask> taskList, List<WFTask> readTaskList, WFParameter parameter) {
        List<WFNodeInfo> nextNodes = schemeExtService.getNextNodes(currentNode.getId(), transportType, parameter);
        if (CollectionUtils.isEmpty(nextNodes)) {
            return false;
        }
        for (WFNodeInfo node : nextNodes) {
            node.setPreviousId(currentNode.getId());
            if (node.getType().equals("conditionnode")) { // 条件节点
                if (calcConditionNode(node, parameter)) {
                    getNextTasks(node, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                } else {
                    getNextTasks(node, WFTransportTypes.Disagree, taskList, readTaskList, parameter);
                }
            } else if (node.getType().equals("confluencenode")) {// 会签节点
                if (parameter.getIsGetAuditer() != null && parameter.getIsGetAuditer()) {
                    getNextTasks(node, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                } else {
                    int confluenceRes;
                    if (transportType == WFTransportTypes.Agree) {
                        confluenceRes = calcConfluenceNode(node, currentNode, parameter, true);
                    } else {
                        confluenceRes = calcConfluenceNode(node, currentNode, parameter, false);
                    }

                    if (confluenceRes == 1) {
                        getNextTasks(node, WFTransportTypes.Agree, taskList, readTaskList, parameter);
                        currentNode.setCfres(true);
                        currentNode.setCfIocName(node.getIocName());
                        currentNode.setCfDbId(node.getDbSuccessId());
                        currentNode.setCfDbSql(node.getDbSuccessSql());
                    } else if (confluenceRes == -1) {
                        getNextTasks(node, WFTransportTypes.Disagree, taskList, readTaskList, parameter);
                        currentNode.setCfres(false);
                        currentNode.setCfIocName(node.getIocName());
                        currentNode.setCfDbId(node.getDbFailId());
                        currentNode.setCfDbSql(node.getDbFailSql());
                    } else {
                        // 添加一个空数据的任务项表示当前流程还未结束
                        WFTask task = new WFTask();
                        taskList.add(task);
                    }
                }


            } else if (node.getType().equals("auditornode")) {
                WFTask task = createTask(node, currentNode, parameter);
                readTaskList.add(task);
            } else if (!node.getType().equals("endround")) {
                if (currentNode.getType().equals("conditionnode")) {
                    WFNodeInfo preActureNode = schemeExtService.getNode(currentNode.getPreviousId());
                    WFTask task = createTask(node, preActureNode, parameter);
                    taskList.add(task);
                } else {
                    WFTask task = createTask(node, currentNode, parameter);
                    taskList.add(task);
                }
            }
        }
        return true;
    }


    /**
     * 创建一个任务处理记录
     *
     * @param parameter   工作流传递参数
     * @param nodeInfo    节点信息
     * @param task        当前任务信息
     * @param result      节点信息 1.同意 2.反对 3.超时
     * @param description 处理意见
     */
    private void createTaskHistory(WFParameter parameter, WFNodeInfo nodeInfo, WFTask task, Integer result, String description) {
        WFTaskHistory taskHistory = new WFTaskHistory();
        taskHistory.setProcessId(parameter.getProcessId());
        taskHistory.setNodeId(nodeInfo.getId());
        taskHistory.setNodeName(nodeInfo.getName());
        taskHistory.setResult(result);
        taskHistory.setDescription(description);

        if (task == null) { //表示创建流程实例
            taskHistory.setTaskType(0);
        } else {
            taskHistory.setTaskType(task.getTaskType());
            taskHistory.setPreviousId(task.getPreviousId());
            taskHistory.setPreviousName(task.getPreviousName());
        }
        taskHistory.setId(UUIDUtils.getOriginalUUIDWithoutBar());
        taskHistory.setCreateUserid(parameter.getUserId());
        taskHistory.setCreateUsername(parameter.getUserName());
        taskHistory.setCreateTime(new Date());
        taskHistoryService.save(taskHistory);
    }


    /**
     * 执行sql语句
     *
     * @param processId 流程实例Id
     * @param dbKey     数据库关键字
     * @param strSql    sql语句
     * @return
     */
    private boolean excuteSql(String processId, String dbKey, String strSql) {
        boolean res = false;
        if (StringUtils.isNotEmpty(dbKey) && StringUtils.isNotEmpty(strSql)) {
            strSql = strSql.replace("{processId}", "#{processId}");
            Map<String, Object> params = new HashMap<>();
            params.put("processId", processId);
            formDbTableService.excuteSqlWithParams(dbKey, strSql, params);
            res = true;
        }
        return res;

    }
}

